// ValidationAspects
// Written by Mike Saunders
// Released under Microsoft Public License (Ms-PL)
using System;
using System.Reflection;
using NUnit.Framework;
using ValidationAspects;
using ValidationAspects.Core;

namespace TestValidationAspects
{
	[TestFixture]
	public class TestValidationContext
	{
		[Test]
		public void Test_constructor6_does_not_throw_for_null_Instance_param()
		{
			new ValidationContext(null, GetType(), null, null, null, null);
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Test_constructor6_does_not_throw_for_null_Type_param()
		{
			new ValidationContext(null, null, null, null, null, null);
		}

		[Test]
		public void Test_constructor2_does_not_throw_for_null_Instance_param()
		{
			Assert.IsNull(new ValidationContext(null, TypeOf<Dummy>.GetProperty(x => x.TheProperty), "s").Instance);
		}

		[Test]
		public void Test_constructor2_does_not_throw_for_null_value_param()
		{
			var context =  new ValidationContext(new Dummy(), TypeOf<Dummy>.GetProperty(x => x.TheProperty), null);

			Assert.IsNotNull(context.Arguments);
			Assert.AreEqual(1, context.Arguments.Length);
			Assert.IsNull(context.Arguments[0]);
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Test_constructor2_throws_for_null_property_param()
		{
			new ValidationContext(null, null, "s");
		}

		[Test]
		public void Test_constructor6_assigns_values()
		{
			Dummy instance = new Dummy();
			Type type = typeof(Dummy);
			PropertyInfo property = TypeOf<Dummy>.GetProperty(x => x.TheProperty);
			MethodInfo method = type.GetMethod("TheMethod");
			ParameterInfo parameter = method.GetParameters()[0];

			object[] methodArgs = new object[] {"s"};
			var context = new ValidationContext(instance, type, property, method, parameter, methodArgs);

			Assert.AreSame(instance, context.Instance);
			Assert.AreSame(type, context.Type);
			Assert.AreSame(property, context.Property);
			Assert.AreSame(method, context.Method);
			Assert.AreSame(parameter, context.Parameter);
			Assert.AreSame(methodArgs, context.Arguments);
		}

		[Test]
		public void Test_constructor2_assigns_values()
		{
			Dummy instance = new Dummy();
			Type type = typeof(Dummy);
			PropertyInfo property = TypeOf<Dummy>.GetProperty(x => x.TheProperty);

			const string value = "s";
			var context = new ValidationContext(instance, property, value);

			MethodInfo method = property.GetSetMethod(true);
			ParameterInfo parameter = method.GetParameters()[0];
			object[] methodArgs = new object[] { value };

			Assert.AreSame(instance, context.Instance);
			Assert.AreSame(type, context.Type);
			Assert.AreSame(property, context.Property);
			Assert.AreSame(method, context.Method);
			Assert.AreSame(parameter, context.Parameter);
			Assert.AreEqual(methodArgs.Length, context.Arguments.Length);
			Assert.AreSame(methodArgs[0], context.Arguments[0]);
		}

		#region Mocks
		public class Dummy
		{
			public string TheProperty { get; set; }

			public void TheMethod(string theParameter) {}
		}
		#endregion
	}
}